type Concat<T extends readonly any[], U extends readonly any[]> = [...T, ...U];
type Push<T extends any[], U> = [...T, U];
type Unshift<T extends any[], U> = [U, ...T];
type ReadonlySome<T, U extends keyof T = keyof T> = Readonly<Pick<T, U>> &
  Omit<T, U>;
type DeepReadonly<T> = {
  readonly [Key in keyof T]: T[Key] extends object
    ? DeepReadonly<T[Key]>
    : T[Key];
};
type TupleToUnion<T> = T extends readonly [infer R, ...infer Rest]
  ? R | TupleToUnion<Rest>
  : never;
type Pop<T extends any[]> = T extends [...infer Rest, any] ? Rest : [];

type Space = " " | "\n" | "\t";
/**
 * '12345' extends `${infer L}${infer Rest}`：L = '1'，Rest = '2345'
 * '12345' extends `${infer Rest}5`：Rest = '1234'
 * '12345' extends `${infer A}3${infer B}`：A = '12'，B = '45'
 * '12345' extends `${infer A}1${infer B}`：A = ''，B = '2345'
 */
type TrimLeft<S extends string> = S extends `${Space}${infer Rest}`
  ? TrimLeft<Rest>
  : S;
type TrimRight<S extends string> = S extends `${infer Rest}${Space}`
  ? TrimRight<Rest>
  : S;
type Trim<S extends string> = TrimLeft<TrimRight<S>>;

type Replace<
  S extends string,
  From extends string,
  To extends string
> = From extends ""
  ? S
  : S extends `${infer L}${From}${infer R}`
  ? `${L}${To}${R}`
  : S;

type ReplaceAll<
  S extends string,
  From extends string,
  To extends string
> = From extends ""
  ? S
  : S extends `${infer L}${From}${infer R}`
  ? `${L}${To}${ReplaceAll<R, From, To>}`
  : S;

type AppendArgument<Fn extends (...args: any[]) => any, A> = Fn extends (
  ...args: infer Rest
) => infer T
  ? (...args: [...Rest, A]) => T
  : never;

type StringToUnion<T extends string> = T extends ""
  ? never
  : T extends `${infer L}${infer Rest}`
  ? L | StringToUnion<Rest>
  : never;

type Merge<
  F extends Record<PropertyKey, any>,
  S extends Record<PropertyKey, any>
> = {
  [Key in keyof F | keyof S]: Key extends keyof S ? S[Key] : F[Key];
};

type Diff<O, O1> = Omit<Omit<O & O1, never>, keyof O & keyof O1>;

type IsUnion<T, U = T> = [T] extends [never]
	? false
	: T extends U
		? Exclude<U, T> extends never
			? false
			: true
		: false;
